#ifndef GEOMETRY_HPP
#define GEOMETRY_HPP

#include "meshTypes_fwd.hpp"

#include <array>

namespace hms
{

/* for sorting vectors by angle with x-axis, this pseudoangle may be used */
double pseudoangle( const Ref<const Vector2s>& );

double pseudoangle( const Mesh&, Index vertex );



Vector2s vectorAverage(const Ref<const Matrix2Xs>&);

template<typename Indices>
Vector2s vectorAverage( const Mesh& mesh, const Indices& vertices );



/* returns the two possible centroids of a square created from a single edge*/
Matrix2s edgeToSquareCenters(
	const Ref<const Vector2s>& start,
	const Ref<const Vector2s>& end
);

Matrix2s edgeToSquareCenters(
	const Mesh&,
	Index edge
);



scalar verticesToArea( const Ref<const Matrix2Xs>& );

template<typename MeshType, typename Indices>
scalar verticesToArea( const MeshBase<MeshType>&, const Indices& vertices );

	

Vector2s verticesToCentroid( const Ref<const Matrix2Xs>&, scalar area=0 );

template<typename MeshType, typename Indices>
Vector2s verticesToCentroid(
	const MeshBase<MeshType>&, const Indices& vertices, scalar area=0
);

template<typename EdgeType>
Vector2s intersectionWithCentroids( const EdgeBase<EdgeType>&, Index order = 1);

bool intersects( const Ref<const Matrix2s>&, const Ref<const Matrix2s>& );

bool intersects(
	const Ref<const Vector2s>&,
	const Ref<const Vector2s>&,
	const Ref<const Vector2s>&,
	const Ref<const Vector2s>&
);

template<typename EdgeType>
bool intersects(
	const Ref<const Vector2s>&,
	const Ref<const Vector2s>&,
	const EdgeBase<EdgeType>&
);

Vector2s mirrorAlongLine( const ParamLine&, const Ref<const Vector2s>& );

template<typename EdgeType>
Vector2s mirrorAlongEdge(const EdgeBase<EdgeType>&, const Ref<const Vector2s>&);

void transformCoords(
	Ref<Array2Xs> transformed,
	const Ref<const Array2Xs>& cartesian,
	const Ref<const Array2Xs>& normals
);

Array2Xs transformCoords(
	const Ref<const Array2Xs>& cartesian,
	const Ref<const Array2Xs>& normals
);

void transformCoordsInPlace(
	Ref<Array2Xs> cartesian,
	const Ref<const Array2Xs>& normals
);

void retransformCoords(
	Ref<Array2Xs> cartesian,
	const Ref<const Array2Xs>& transformed,
	const Ref<const Array2Xs>& normals
);

Array2Xs retransformCoords(
	const Ref<const Array2Xs>& transformed,
	const Ref<const Array2Xs>& normals
);

void retransformCoordsInPlace(
	Ref<Array2Xs> transformed,
	const Ref<const Array2Xs>& normals
);

template<typename EdgeType>
Vector2s transformCoords(
	const Ref<const Vector2s>&, const EdgeBase<EdgeType>&
);

template<typename EdgeType>
Vector2s retransformCoords(
	const Ref<const Vector2s>&, const EdgeBase<EdgeType>&
);

}

#include "geometry.tpp"

#endif